// MySplitter.cpp : implementation file
//

#include "stdafx.h"
#include "Resource.h"
#include "MySplitter.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

COLORREF CMySplitter::m_clrPen1[] = { RGB(205, 230, 245), RGB(195, 245, 175) };
COLORREF CMySplitter::m_clrPen2[] = { RGB(175, 200, 215), RGB(165, 215, 145) };
COLORREF CMySplitter::m_clrPen3[] = { RGB(145, 170, 185), RGB(135, 185, 115) };
COLORREF CMySplitter::m_clrPenArrow[] = { RGB(0, 0, 0), RGB(0, 0, 255) };
/////////////////////////////////////////////////////////////////////////////
// CMySplitter

CMySplitter::CMySplitter()
{
	m_bOnHot = FALSE;
	m_bCaptured = FALSE;
	m_bInResizeLoop = FALSE;
	m_bDownedOnHot = FALSE;
	m_bCollapsed = FALSE;
	m_nLastLeft = 200;
	m_nRightDistance = 7;
}

CMySplitter::~CMySplitter()
{
}


BEGIN_MESSAGE_MAP(CMySplitter, CWnd)
	//{{AFX_MSG_MAP(CMySplitter)
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_WINDOWPOSCHANGED()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMySplitter message handlers

void CMySplitter::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CRect rcClient(0, 0, m_cx, m_cy);
	COLORREF clrBtnFace = GetSysColor(COLOR_BTNFACE);
//	COLORREF clrBtnFace = RGB(0, 255, 0);
	++rcClient.left;
	dc.FillSolidRect(rcClient, clrBtnFace);
	int nHotHeight = (int)(rcClient.bottom / 6.6);
	CRect rcHot(0, (rcClient.bottom - nHotHeight) / 2 - 1, 7, 0);
	CRect rcHot0(rcHot);
	rcHot.bottom = rcHot.top + nHotHeight;

	int nColorIndex = m_bOnHot? 1: 0;
//	CPen pen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));//RGB(192, 192, 255)) 
	CPen pen(PS_SOLID, 1, RGB(192, 192, 255));
	CPen pen1(PS_SOLID, 1, m_clrPen1[nColorIndex]);
	CPen pen2(PS_SOLID, 1, m_clrPen2[nColorIndex]);
	CPen pen3(PS_SOLID, 1, m_clrPen3[nColorIndex]);
	CPen penArrow(PS_SOLID, 1, m_clrPenArrow[nColorIndex]);

	CPen *pOldPen = dc.SelectObject(&pen);

	dc.Rectangle(rcHot.left + 1, rcHot.top + 1, rcHot.right, rcHot.bottom - 1);
	dc.Rectangle(rcHot.left + 1, rcHot.top, rcHot.right - 1, rcHot.bottom);
	dc.FillSolidRect(rcHot.left + 1, rcHot.top + 2, rcHot.right - 2, rcHot.Height() - 4, RGB(255, 255, 255));

	if(m_bDownedOnHot && m_bOnHot)
	{
		dc.SelectObject(&pen3);
		dc.MoveTo(1, rcHot.top);
		dc.LineTo(1, rcHot.bottom - 3);
		dc.SelectObject(&pen2);
		dc.MoveTo(2, rcHot.top + 1);
		dc.LineTo(2, rcHot.bottom - 3);
		dc.SelectObject(&pen1);
		dc.MoveTo(3, rcHot.top + 1);
		dc.LineTo(3, rcHot.bottom - 2);
	}
	else
	{
		dc.SelectObject(&pen1);
		dc.MoveTo(4, rcHot.top + 2);
		dc.LineTo(4, rcHot.bottom - 1);
		dc.SelectObject(&pen2);
		dc.MoveTo(5, rcHot.top + 3);
		dc.LineTo(5, rcHot.bottom - 1);
		dc.SelectObject(&pen3);
		dc.MoveTo(6, rcHot.top + 3);
		dc.LineTo(6, rcHot.bottom - 2);
	}
	
	dc.SelectObject(&penArrow);
	int nHotMiddleY = rcHot.top + nHotHeight / 2;
	if(m_bCollapsed)
	{
		dc.MoveTo(2, nHotMiddleY - 3);
		dc.LineTo(6, nHotMiddleY + 1);
		dc.MoveTo(2, nHotMiddleY - 2);
		dc.LineTo(5, nHotMiddleY + 1);
		dc.MoveTo(2, nHotMiddleY + 3);
		dc.LineTo(6, nHotMiddleY - 1);
		dc.MoveTo(2, nHotMiddleY + 2);
		dc.LineTo(5, nHotMiddleY - 1);
	}
	else
	{
		dc.MoveTo(2, nHotMiddleY);
		dc.LineTo(6, nHotMiddleY - 4);
		dc.MoveTo(3, nHotMiddleY);
		dc.LineTo(6, nHotMiddleY - 3);
		dc.MoveTo(2, nHotMiddleY);
		dc.LineTo(6, nHotMiddleY + 4);
		dc.MoveTo(3, nHotMiddleY);
		dc.LineTo(6, nHotMiddleY + 3);
	}
	
	dc.SelectObject(pOldPen);
}

void CMySplitter::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);
	m_cx = cx;
	m_cy = cy;
	Invalidate(FALSE);
	UpdateWindow();
}

void CMySplitter::OnMouseMove(UINT nFlags, CPoint point) 
{
	if(m_bInResizeLoop)
	{
		if((!m_bOnHot && m_oldX != point.x) || (m_bOnHot && abs(m_oldX - point.x) > 3))
		{
			CDC *pDC = CDC::FromHandle(::GetDC(NULL));
			CRect rect(point.x - m_ptDowned.x, 0, 0, m_cy + 10);
			ClientToScreen(rect);
			CRect rcParent;
			m_pParentWnd->GetClientRect(rcParent);
			m_pParentWnd->ClientToScreen(rcParent);
			if(rect.left <= rcParent.left)
			{
				rect.left = rcParent.left;
			}
			rect.right = rect.left + 7;
			if(rect.right >= rcParent.right - m_nRightDistance)
			{
				rect.right = rcParent.right - m_nRightDistance;
				rect.left = rect.right - 7;
			}

			if(m_oldRect.left != rect.left)
			{
				pDC->InvertRect(m_oldRect);
				pDC->InvertRect(rect);
				m_oldRect = rect;
			}
			
			::ReleaseDC(NULL, pDC->GetSafeHdc());
			m_oldX = point.x;
		}
	}
	CRect rcClient(0, 0, m_cx, m_cy);
	if(rcClient.PtInRect(point))
	{
		if(!m_bCaptured)
		{
			SetCapture();
			m_bCaptured = TRUE;
		}
		int nHotHeight = (int)(rcClient.bottom / 6.6);
		CRect rcHot(0, (rcClient.bottom - nHotHeight) / 2 - 1, 7, 0);
		rcHot.bottom = rcHot.top + nHotHeight;
		BOOL bOnHot = rcHot.PtInRect(point);

		if(bOnHot)
		{
			SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
		}
		else
		{
			SetCursor((HCURSOR)GetClassLong(m_hWnd, GCL_HCURSOR));
		}
		if(m_bOnHot != bOnHot)
		{
			CDC *pDC = CDC::FromHandle(::GetDC(NULL));
			pDC->InvertRect(m_oldRect);

			m_bOnHot = bOnHot;
			Invalidate(FALSE);
			UpdateWindow();

			pDC->InvertRect(m_oldRect);
			::ReleaseDC(NULL, pDC->GetSafeHdc());
		}
	}
	else// if()
	{
		if(!m_bInResizeLoop && !m_bDownedOnHot)
		{
			ReleaseCapture();
			m_bCaptured = FALSE;
		}
		if(m_bOnHot)
		{
			CDC *pDC = CDC::FromHandle(::GetDC(NULL));
			pDC->InvertRect(m_oldRect);

			m_bOnHot = FALSE;
			Invalidate(FALSE);
			UpdateWindow();

			pDC->InvertRect(m_oldRect);
			::ReleaseDC(NULL, pDC->GetSafeHdc());
		}
	}
	CWnd::OnMouseMove(nFlags, point);
}

void CMySplitter::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CWnd::OnLButtonDblClk(nFlags, point);
}

BOOL CMySplitter::Create(CWnd *pWndParent)
{
	static BOOL bRegistered = FALSE;
	if(!bRegistered)
	{
		WNDCLASS wndclass;
		memset(&wndclass, 0, sizeof(WNDCLASS));
		wndclass.hbrBackground = (HBRUSH)NULL_BRUSH;
		wndclass.hCursor = LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_SPLIT));
		wndclass.hIcon = 0;
		wndclass.hInstance = AfxGetInstanceHandle();
		wndclass.lpfnWndProc = ::DefWindowProc;
		wndclass.lpszClassName = "MySplitter";
		wndclass.lpszMenuName = NULL;
		wndclass.style = CS_HREDRAW|CS_VREDRAW;
		VERIFY(AfxRegisterClass(&wndclass));
		bRegistered = TRUE;
	}
	m_pParentWnd = pWndParent;
	return CWnd::Create("MySplitter", NULL, WS_CHILD|WS_VISIBLE, CRect(0, 0, 7, 7), pWndParent, (UINT)-1);
}

void CMySplitter::OnLButtonDown(UINT nFlags, CPoint point) 
{
	m_ptDowned = point;
	if(m_bOnHot)
	{
		m_bDownedOnHot = TRUE;
		Invalidate(FALSE);
		UpdateWindow();
	}
	else
	{
		
	}
	m_bInResizeLoop = TRUE;
	CWnd::OnLButtonDown(nFlags, point);
}

void CMySplitter::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if(!m_oldRect.IsRectEmpty())
	{
		CDC *pDC = CDC::FromHandle(::GetDC(NULL));
		pDC->InvertRect(m_oldRect);
		::ReleaseDC(NULL, pDC->GetSafeHdc());
		m_pParentWnd->ScreenToClient(m_oldRect);
		m_pParentWnd->SendMessage(WM_SPLITTER_MOVED, 0, MAKELPARAM(m_oldRect.left, m_oldRect.top));
		m_oldRect.SetRectEmpty();
	}
	else if(m_bDownedOnHot)
	{
		m_bCollapsed = !m_bCollapsed;
		m_pParentWnd->SendMessage(WM_SPLITTER_MOVED, 0, MAKELPARAM(m_bCollapsed? 0: m_nLastLeft, 0));
	}

	m_bInResizeLoop = FALSE;
	
	if(m_bDownedOnHot)
	{
		m_bDownedOnHot = FALSE;
		Invalidate(FALSE);
		UpdateWindow();
	}
	CWnd::OnLButtonUp(nFlags, point);
}

BOOL CMySplitter::PreTranslateMessage(MSG* pMsg) 
{
	return CWnd::PreTranslateMessage(pMsg);
}

BOOL CMySplitter::RelayEvent(MSG *pMsg)
{
	if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE && m_bInResizeLoop)
	{
		CancelResizeLoop();
		return TRUE;
	}
	return FALSE;
}

void CMySplitter::CancelResizeLoop()
{
	m_bInResizeLoop = FALSE;
	CDC *pDC = CDC::FromHandle(::GetDC(NULL));
	pDC->InvertRect(m_oldRect);
	::ReleaseDC(NULL, pDC->GetSafeHdc());
	m_oldRect.SetRectEmpty();
	CPoint pt;
	GetCursorPos(&pt);
	ScreenToClient(&pt);
	OnMouseMove(0, pt);
}

void CMySplitter::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) 
{
	CWnd::OnWindowPosChanged(lpwndpos);
	CRect rect;
	GetWindowRect(rect);
	m_pParentWnd->ScreenToClient(rect);
	BOOL bCollapsed = (rect.left < 1);
	if(bCollapsed != m_bCollapsed)
	{
		m_bCollapsed = bCollapsed;
		Invalidate(FALSE);
		UpdateWindow();
	}
	if(!bCollapsed)
	{
		m_nLastLeft = rect.left;
	}
}

void CMySplitter::ReleaseCapture()
{
	::ReleaseCapture();
	m_bCaptured = FALSE;
}
